<!DOCTYPE html>
<html>

<head>
<title>jQuery-CSV Testing</title>
<meta charset="UTF-8" />
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" />
<script src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
<script src="../src/jquery.csv.js"></script>
<script>
$(document).ready(function() {

  // initialize the data for the 'core' module
  function coreDataInit() {
    toArray = '"You will come back stronger then ever","like Lance Armstrong","but with two balls"';
    fromArray = ["You will come back stronger then ever","like Lance Armstrong","but with two balls"];

    toArrays = '';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."\n';
    toArrays += '"All work","and no play","makes Jack","a dull boy..."';

    fromArrays = [];
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);
    fromArrays.push(["All work","and no play","makes Jack","a dull boy..."]);

    toObjects = '"ID","iManufacturer","iMPartNumber","iSerialNumber","iSimCategory","iPartType","iDescription","iGroup","iLocation","iSold"\n';
    toObjects += '"1","Evans & Sutherland","230-132-111AA","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"2","Evans & Sutherland","230-132-111AA","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"3","Evans & Sutherland","230-120-112AC","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"4","Evans & Sutherland","230-120-112AC","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"5","Evans & Sutherland","230-120-112AC","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"6","Evans & Sutherland","230-120-112AC","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"7","Evans & Sutherland","230-120-112AC","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"8","Evans & Sutherland","230-120-112AC","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"9","Evans & Sutherland","230-120-112AC","","Visual","PCB","","1","Offsite",""\n';
    toObjects += '"10","Evans & Sutherland","230-121-150AC","","Visual","PCB","","1","Offsite",""';

    fromObjects = [];
    fromObjects.push({ID:"1",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-132-111AA",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"2",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-132-111AA",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"3",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-120-112AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"4",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-120-112AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"5",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-120-112AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"6",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-120-112AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"7",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-120-112AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"8",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-120-112AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"9",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-120-112AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});
    fromObjects.push({ID:"10",iManufacturer:"Evans & Sutherland",iMPartNumber:"230-121-150AC",iSerialNumber:"",iSimCategory:"Visual",iPartType:"PCB",iDescription:"",iGroup:"1",iLocation:"Offsite",iSold:""});

    testRFCCompliance1 = '';
    testRFCCompliance1 += 'aaa,bbb,ccc\r\n';
    testRFCCompliance1 += 'zzz,yyy,xxx\r\n';
    resultRFCCompliance1 = [];
    resultRFCCompliance1.push(['aaa','bbb','ccc']);
    resultRFCCompliance1.push(['zzz','yyy','xxx']);
    testRFCCompliance2 = '';
    testRFCCompliance2 += 'aaa,bbb,ccc\r\n';
    testRFCCompliance2 += 'zzz,yyy,xxx';
    resultRFCCompliance2 = [];
    resultRFCCompliance2.push(['aaa','bbb','ccc']);
    resultRFCCompliance2.push(['zzz','yyy','xxx']);
    testRFCCompliance3 =  '';
    testRFCCompliance3 += 'field1,field2,field3\r\n';
    testRFCCompliance3 += 'aaa,bbb,ccc\r\n';
    testRFCCompliance3 += 'zzz,yyy,xxx\r\n';
    resultRFCCompliance3 = [];
    resultRFCCompliance3.push({field1:'aaa',field2:'bbb',field3:'ccc'});
    resultRFCCompliance3.push({field1:'zzz',field2:'yyy',field3:'xxx'});
    testRFCCompliance4 = '';
    testRFCCompliance4 += 'aaa , bbb, c  cc\r\n';
    resultRFCCompliance4 = ['aaa ',' bbb',' c  cc'];
    testRFCCompliance5 = '';
    testRFCCompliance5 += '"aaa","bbb","ccc"\r\n';
    testRFCCompliance5 += 'zzz,yyy,xxx';
    resultRFCCompliance5 = [];
    resultRFCCompliance5.push(['aaa','bbb','ccc']);
    resultRFCCompliance5.push(['zzz','yyy','xxx']);
    testRFCCompliance6 = '';
    testRFCCompliance6 += '"aaa","b\r\nbb","cc,c"\r\n';
    testRFCCompliance6 += 'zzz,yyy,xxx';
    resultRFCCompliance6 = [];
    resultRFCCompliance6.push(['aaa','b\r\nbb','cc,c']);
    resultRFCCompliance6.push(['zzz','yyy','xxx']);
    testRFCCompliance7 = '';
    testRFCCompliance7 += '"aaa","b""bb","ccc"';
    resultRFCCompliance7 = ['aaa', 'b"bb', 'ccc'];
    testRFCComplianceA1 = '';
    testRFCComplianceA1 += 'aaa,,ccc';
    resultRFCComplianceA1 = ['aaa', '', 'ccc'];
    testRFCComplianceA2 = '';
    testRFCComplianceA2 += '"aaa","","ccc"';
    resultRFCComplianceA2 = ['aaa', '', 'ccc'];
    testRFCComplianceA3 = '';
    testRFCComplianceA3 += '"aaa","bbb",';
    resultRFCComplianceA3 = ['aaa', 'bbb', ''];

    testControl = [];
    testControl.push('"1","he said ""you are crazy""","one "", two "", three """');
    testControl.push("'2','he said ''you are crazy''','one '', two '', three '''");
    testControl.push('"3";"he said ""you are crazy""";"one "", two "", three """');
    testControl.push('"4"|"he said ""you are crazy"""|"one "", two "", three """');
    resultControl = [];
    resultControl.push(['1','he said "you are crazy"','one ", two ", three "']);
    resultControl.push(['2','he said \'you are crazy\'','one \', two \', three \'']);
    resultControl.push(['3','he said "you are crazy"','one ", two ", three "']);
    resultControl.push(['4','he said "you are crazy"','one ", two ", three "']);
    testControlArrays = '';
    testControlArrays += '*Look*:*there\'s two women*:*fucking a polar bear!*\n'; 
    testControlArrays += '*Don\'t*:*tell me these things*:*not now man.*\n'; 
    resultControlArrays = [];
    resultControlArrays.push(['Look','there\'s two women','fucking a polar bear!']);
    resultControlArrays.push(['Don\'t','tell me these things','not now man.']);
    testControlObjects = '';
    testControlObjects += '^preposition^&^evaluation^&^response^\n';
    testControlObjects += '^One toke?^&^you poor fool!^&^wait till you see those goddamn bats.^\n';
    testControlObjects += '^Wait!^&^we can\'t stop here^&^this is bat country.^\n';
    resultControlObjects = [];
    resultControlObjects.push({preposition:'One toke?',evaluation:'you poor fool!',response:'wait till you see those goddamn bats.'});
    resultControlObjects.push({preposition:'Wait!',evaluation:'we can\'t stop here',response:'this is bat country.'});

    testArrays = '';
    testArrays += '1,0,0,0,0\n';
    testArrays += '0,2,0,0,0\n';
    testArrays += '0,0,3,0,0\n';
    testArrays += '0,0,0,4,0\n';
    testArrays += '0,0,0,0,5\n';
    resultArraysStart = [];
    resultArraysStart.push(['0','0','3','0','0']);
    resultArraysStart.push(['0','0','0','4','0']);
    resultArraysStart.push(['0','0','0','0','5']);
    resultArraysEnd = [];
    resultArraysEnd.push(['1','0','0','0','0']);
    resultArraysEnd.push(['0','2','0','0','0']);
    resultArraysEnd.push(['0','0','3','0','0']);
    testObjects = '';
    testObjects += 'first,second,third,fourth,fifth\n';
    testObjects += testArrays;
    resultObjectsStart = [];
    resultObjectsStart.push({first:'0',second:'0',third:'3',fourth:'0',fifth:'0'});
    resultObjectsStart.push({first:'0',second:'0',third:'0',fourth:'4',fifth:'0'});
    resultObjectsStart.push({first:'0',second:'0',third:'0',fourth:'0',fifth:'5'});
    resultObjectsEnd = [];
    resultObjectsEnd.push({first:'1',second:'0',third:'0',fourth:'0',fifth:'0'});
    resultObjectsEnd.push({first:'0',second:'2',third:'0',fourth:'0',fifth:'0'});
    resultObjectsEnd.push({first:'0',second:'0',third:'3',fourth:'0',fifth:'0'});

    testHook1 = '';
    testHook1 += '734,4.5,sda,"555","4523.35","af323"';
    resultHook1 = [];
    resultHook1.push([734,4.5,"sda",555,4523.35,"af323"]);
    testHook2 = '';
    testHook2 += '"You have the right","to remain silent","but","I\'m gonna make","ya scream!"';
    resultHook2 = [];
    resultHook2.push(["I\'m gonna make","ya scream!"]);
    testHook3 = '';
    testHook3 += '5.55555,7.7777777,1.1,0';
    resultHook3 = [];
    resultHook3.push(["5.56","7.78","1.10","0.00"]);
    testHook4 = '';
    testHook4 += 'fluffy\n';
    testHook4 += 'nutter\n';
    testHook4 += 'funny\n';
    testHook4 += 'fuffer\n';
    resultHook4 = [];
    resultHook4.push(['funny']);
    resultHook4.push(['fuffer']);

    testNodeCallbacks = '';
    testNodeCallbacks += '"What are you","knittin\' a f*&%ing sweater"\n';
    testNodeCallbacks += '"I\'m trying to put some","tigers balm","on this jungle\'s nuts"';
    resultNodeCallbacks = [];
    resultNodeCallbacks.push(["What are you","knittin' a f*&%ing sweater"]);
    resultNodeCallbacks.push(["I'm trying to put some","tigers balm","on this jungle's nuts"]);
  }

  module("core", { setup:function(){ coreDataInit() }});
  test("Parsing - to Array", function() {
    expect(1);
    stop();
    var output = $.csv.toArray(toArray);
    start();
    deepEqual(output, fromArray, "$csv.toArray()");
  });

//  TODO: Impmlement $.csv.fromArray()
//  test("Parsing - from Array", function() {
//    expect(1);
//    stop();
//    var output = $.fromArray(fromArray);
//    start();
//    deepEqual(output, toArray, "$.csv.fromArray()");
//  });

  test("Parsing - to Arrays", function() {
    expect(1);
    stop();
    var output = $.csv.toArrays(toArrays);
    start();
    deepEqual(output, fromArrays, "$.csv.toArrays()");
  });

  test("Parsing - from Arrays", function() {
    expect(1);
    stop();
    var output = $.csv.fromArrays(fromArrays);
    start();
    deepEqual(output, toArrays, "$.csv.fromArrays()");
  });

  test("Parsing - to Objects", function() {
    expect(1);
    stop();
    var output = $.csv.toObjects(toObjects);
    start();
    deepEqual(output, fromObjects, "$.csv.toObjects()");
  });

    test("Parsing - from Objects", function() {
    expect(1);
    stop();
    var output = $.csv.fromObjects(fromObjects);
    start();
    deepEqual(output, toObjects, "$.csv.fromObjects()");
  });

  test("RFC 4180 Compliance", function() {
    expect(10);
    stop();
    var output = $.csv.toArrays(testRFCCompliance1);
    start();
    deepEqual(output, resultRFCCompliance1, "Rule #1 - One entry per line, each line ends with a newline");
    stop();
    var output = $.csv.toArrays(testRFCCompliance2);
    start();
    deepEqual(output, resultRFCCompliance2, "Rule #2 - Trailing newline at the end of the file omitted");
    stop();
    var output = $.csv.toObjects(testRFCCompliance3);
    start();
    deepEqual(output, resultRFCCompliance3, "Rule #3 - First row contains header data");
    stop();
    var output = $.csv.toArray(testRFCCompliance4);
    start();
    deepEqual(output, resultRFCCompliance4, "Rule #4 - Spaces are considered data and entries should not contain a trailing comma");
    stop();
    var output = $.csv.toArrays(testRFCCompliance5);
    start();
    deepEqual(output, resultRFCCompliance5, "Rule #5 - Lines may or may not be delimited by double-quotes");
    stop();
    var output = $.csv.toArrays(testRFCCompliance6);
    start();
    deepEqual(output, resultRFCCompliance6, "Rule #6 - Fields containing line breaks, double-quotes, and commas should be enclosed in double-quotes");
    stop();
    var output = $.csv.toArray(testRFCCompliance7);
    start();
    deepEqual(output, resultRFCCompliance7, "Rule #7 - If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with another double quote");
    stop();
    var output = $.csv.toArray(testRFCComplianceA1);
    start();
    deepEqual(output, resultRFCComplianceA1, "Amendment #1 - An unquoted field may or may not contain a null value");
    stop();
    var output = $.csv.toArray(testRFCComplianceA2);
    start();
    deepEqual(output, resultRFCComplianceA2, "Amendment #2 - A quoted field may or may not contain a null value");
    stop();
    var output = $.csv.toArray(testRFCComplianceA3);
    start();
    deepEqual(output, resultRFCComplianceA3, "Amendment #3 - The last field in an entry may or may not contain a null value");
  });

  test("Custom Control Chars - Delimiter, Separator", function() {
    expect(6);
    stop();
    var output = $.csv.toArray(testControl[0]);
    start();
    deepEqual(output, resultControl[0], "standard delimiter/separator/escaper");
    stop();
    var output = $.csv.toArray(testControl[1], {
      delimiter:"'"
    });
    start();
    deepEqual(output, resultControl[1], "custom delimiter");
    stop();
    var output = $.csv.toArray(testControl[2], {
      separator:';'
    });
    start();
    deepEqual(output, resultControl[2], "custom separator");
    stop();
    var output = $.csv.toArray(testControl[3], {
      separator:'|'
    });
    start();
    deepEqual(output, resultControl[3], "regex escaped inputs");
    stop();
    var output = $.csv.toArrays(testControlArrays, {
      delimiter: '*',
      separator: ':'
    });
    start();
    deepEqual(output, resultControlArrays, "toArrays()");
    stop();
    var output = $.csv.toObjects(testControlObjects, {
      delimiter: '^',
      separator: '&'
    });
    start();
    deepEqual(output, resultControlObjects, "toObjets()");
  });

  test("Custom Arguments - Start, End", function() {
    expect(4);
    stop();
    var output = $.csv.toArrays(testArrays, {
      start:3
    });
    start();
    deepEqual(output, resultArraysStart, "toArrays() - 'start' argment");
    stop();
    var output = $.csv.toArrays(testArrays, {
      end:3
    });
    start();
    deepEqual(output, resultArraysEnd, "toArrays() - 'end' argment");
    stop();
    var output = $.csv.toObjects(testObjects, {
      start:3
    });
    start();
    deepEqual(output, resultObjectsStart, "toObjects() - 'start' argment");
    stop();
    var output = $.csv.toObjects(testObjects, {
      end:3
    });
    start();
    deepEqual(output, resultObjectsEnd, "toObjects() - 'end' argment");
  });
  
  test("Hooks & User-Defined Callbacks", function() {
    expect(4);
    stop();
    var output = $.csv.toArrays(testHook1, {
      onParseValue: $.csv.hooks.castToScalar
    });
    start();
    deepEqual(output, resultHook1, "onParseValue - casting values to scalar types");
    stop();
    var columnRange = function(value, state) {
      var start = 4;
      var end = 5;
      if(state.colNum >= start && state.colNum <= end) {
        return value;
      }
      return false;
    }    
    var output = $.csv.toArrays(testHook2, {
      onParseValue: columnRange
    });
    start();
    deepEqual(output, resultHook2, "onParseValue - selecting a column range");
    stop();
    var toPrecision = function(value, state) {
      var isNumber = /^[\d\.]+$/;
      
      if (value.length) {
        if (isNaN(value)) {
          return value;
        } else if (isNumber.test(value)){
          return parseFloat(value).toFixed(2);
        }
      } else {
        return undefined;
      }
    }
    var output = $.csv.toArrays(testHook3, {
      onParseValue: toPrecision
    });
    start();
    deepEqual(output, resultHook3, "onParseValue - formatting to 2-digit precision");
    stop();
    var rowRange = function(entry, state) {
      var start = 3;
      var end = 4;
      if(state.rowNum >= start && state.rowNum <= end) {
        return entry;
      }
      return false;
    }
    var output = $.csv.toArrays(testHook4, {
      onParseEntry: rowRange
    });
    start();
    deepEqual(output, resultHook4, "onParseEntry - selecting a row range");
  });

  test("Node.js", function() {
    expect(1);
    stop();
    $.csv.toArrays(testNodeCallbacks, {}, function(err, output) {
      deepEqual(output, resultNodeCallbacks, "Node.js-style callback support");
    });
    start();
  });
});
</script>
</head>

<body>
  <h1 id="qunit-header">jQuery-CSV Testing</h1>
  <h2 id="qunit-banner"></h2>
  <h2 id="qunit-userAgent"></h2>
  <ol id="qunit-tests">
  </ol>
</body>

</html>